package com.authine.cloudpivot.ext.service.account.impl;

import com.authine.cloudpivot.ext.Enum.TradeDirection;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.PlatformConst;
import com.authine.cloudpivot.ext.dto.finance.AccountDto;
import com.authine.cloudpivot.ext.dto.model.settle.SettleDetail;
import com.authine.cloudpivot.ext.dto.model.trade.Trade;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.service.account.AccountService;
import com.authine.cloudpivot.ext.service.account.OrganizationAccountService;
import com.authine.cloudpivot.ext.service.trade.TradeService;
import com.authine.cloudpivot.ext.service.trade.impl.TradeServiceImpl;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.cloudpivot.ext.utils.system.OrgUtils;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import org.springframework.util.StopWatch;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class OrganizationAccountServiceImpl implements OrganizationAccountService {
    public static AccountService accountService = new AccountServiceImpl();
    public static TradeService tradeService = new TradeServiceImpl();

    /**
     * 财务用
     *
     * @param settleIdList
     * @param type 1=余额增加，0=余额减
     * @return
     */

    public Boolean saveByPayment(List<String> settleIdList, int type) {
        //根据结算获取交易
        List<SettleDetail> settleDetailList = JdbcTemplateUtils.builder(ModelConst.T_SETTLE_DETAIL).selectField("*")
                .in("settle_id", settleIdList)
                .queryForPOJOList(SettleDetail.class);

        List<Trade> trades = new ArrayList<>();
        settleDetailList.stream().collect(Collectors.groupingBy(SettleDetail::getTrade_id))
                .forEach((tradeIdKey, settleDetailValues) -> {
                    BigDecimal total = CalculatorUtils.sum(settleDetailValues, BiFunctionConst.settleDetailTotalFun);
                    Trade tradeEntity = tradeService.loadById(tradeIdKey);
                    trades.add(
                            Trade.builder()
                                    .id(tradeIdKey)
                                    .amount(total)
                                    .direction(tradeEntity.getDirection())
                                    .organization_id(tradeEntity.getOrganization_id())
                                    .build());
                });

        StopWatch stopWatch = new StopWatch();
        stopWatch.start("财务付款更改信用");

        //获得交易的组织列表
        List<String> tradeOrgIds = trades.stream().map(t -> t.getOrganization_id().getId()).collect(Collectors.toList());
        List<OrganizationDto> tradeOrgList = OrgUtils.getOrgListByOrgIds(tradeOrgIds);
        Assert.notEmpty(tradeOrgList, "交易组织异常");

        //获取交易组织的结算账户
        List<String> accountIds = tradeOrgList.stream().filter(t -> StringUtils.isNotEmpty(t.getAccount_id()))
                .map(OrganizationDto::getAccount_id).collect(Collectors.toList());
        List<AccountDto> accountDtoList = JdbcTemplateUtils.builder(ModelConst.T_ACCOUNT).selectField("*")
                .in("id", accountIds)
                .queryForPOJOList(AccountDto.class);
        Assert.notEmpty(accountDtoList, "结算组织账户为空");

        trades.stream().collect(Collectors.groupingBy(Trade::getDirection))
                .forEach(((tradeDirectionKey, tradeModes) -> {
                    if (tradeDirectionKey.equals(TradeDirection.Sale.name())) {
                        tradeModes.stream().collect(Collectors.groupingBy(Trade::getOrganization_id))
                                .forEach((organizationIdKey, tradeModesSub) -> {
                                    //获取组织
                                    OrganizationDto organization = tradeOrgList.stream().filter(t -> t.getId().equals(organizationIdKey.getId())).collect(Collectors.toList()).get(0);
                                    //获取组织账户
                                    AccountDto account = accountService.loadById(organization.getAccount_id());
                                    Assert.notNull(account, "请联系平台客服为["+organization.getId()+"]添加结算账户");
                                    BigDecimal availableLimit = account.getAvailable_limit();

                                    if (type == 1) {
                                        //客户可用额度增加
                                        for (Trade trade : tradeModesSub) {
                                            availableLimit = BigDecimalUtils.add(availableLimit, trade.getAmount());
                                        }
                                    } else {
                                        //客户可用额度减少
                                        for (Trade trade : tradeModesSub) {
                                            availableLimit = BigDecimalUtils.sub(availableLimit, trade.getAmount());
                                        }
                                    }
                                    account.setAccount_balance(availableLimit);
                                    accountService.update(account);
                                });
                    } else {
                        tradeModes.stream().collect(Collectors.groupingBy(Trade::getOrganization_id))
                                .forEach((organizationIdKey, tradeModesSub) -> {
                                    //获取组织
                                    OrganizationDto organization = tradeOrgList.stream().filter(t -> t.getId().equals(organizationIdKey.getId())).collect(Collectors.toList()).get(0);
                                    //获取组织账户
                                    AccountDto account = accountService.loadById(organization.getAccount_id());
                                    Assert.notNull(account, "请联系平台客服为["+organization.getId()+"]添加结算账户");
                                    BigDecimal accountBalance = account.getAccount_balance();
                                    if (1 == type) {
                                        //供应商余额减少
                                        for (Trade trade : tradeModesSub) {
                                            accountBalance = BigDecimalUtils.sub(accountBalance, trade.getAmount());
                                        }
                                    } else {
                                        //供应商余额增加
                                        for (Trade trade : tradeModesSub) {
                                            accountBalance = BigDecimalUtils.add(accountBalance, trade.getAmount());
                                        }
                                    }
                                    account.setAccount_balance(accountBalance);
                                    accountService.update(account);
                                });
                    }
                }));
        AccountDto platformAccount = accountService.loadById(PlatformConst.ORGANIZATION_ACCOUND_ID);
        BigDecimal platformAvailableLimit = platformAccount.getAvailable_limit(), platformAccountBalance = platformAccount.getAccount_balance();

        for (Trade trade : trades) {
            if (trade.getDirection().equals(TradeDirection.Sale.name())) {
                if (1 == type) {//平台可用额度增加
                    platformAvailableLimit = BigDecimalUtils.sub(platformAvailableLimit, trade.getAmount());
                } else {
                    //平台可用额度增加
                    platformAvailableLimit = BigDecimalUtils.add(platformAvailableLimit, trade.getAmount());
                }
            } else {
                if (1 == type) {
                    //平台可用额度减少
                    platformAccountBalance = BigDecimalUtils.add(platformAccountBalance, trade.getAmount());

                } else {
                    //平台可用额度减少
                    platformAccountBalance = BigDecimalUtils.sub(platformAccountBalance, trade.getAmount());
                }
            }
        }

        platformAccount.setAvailable_limit(platformAvailableLimit);
        platformAccount.setAccount_balance(platformAccountBalance);
        accountService.update(platformAccount);

        stopWatch.stop();
        String prettyPrint = stopWatch.prettyPrint();
        log.info(prettyPrint);
        return true;
    }

    @Override
    public Boolean refundByPayment(List<String> settleIdList) {
        //根据结算获取交易
        List<SettleDetail> settleDetailList = JdbcTemplateUtils.builder(ModelConst.T_SETTLE_DETAIL).selectField("*")
                .in("settle_id", settleIdList)
                .queryForPOJOList(SettleDetail.class);
        if (settleDetailList.size()==0){
            return true;
        }
        List<Trade> trades = new ArrayList<>();
        settleDetailList.stream().collect(Collectors.groupingBy(SettleDetail::getTrade_id))
                .forEach((tradeIdKey, settleDetailValues) -> {
                    BigDecimal total = CalculatorUtils.sum(settleDetailValues, BiFunctionConst.settleDetailTotalFun);
                    Trade tradeEntity = JdbcTemplateUtils.builder(ModelConst.T_TRADE).selectField("*")
                            .eq("id", tradeIdKey)
                            .queryForPOJO(Trade.class);
                    trades.add(
                            Trade.builder()
                                    .id(tradeIdKey)
                                    .amount(total)
                                    .direction(tradeEntity.getDirection())
                                    .organization_id(tradeEntity.getOrganization_id())
                                    .build());
                });

        StopWatch stopWatch = new StopWatch();
        stopWatch.start("财务更改信用");
        //获得交易的组织列表
        List<String> tradeOrgIds = trades.stream().map(t -> t.getOrganization_id().getId()).collect(Collectors.toList());
        List<OrganizationDto> tradeOrgList = OrgUtils.getOrgListByOrgIds(tradeOrgIds);

        List<String> accountIds = tradeOrgList.stream().filter(t -> StringUtils.isNotEmpty(t.getAccount_id()))
                .map(OrganizationDto::getAccount_id).collect(Collectors.toList());
        List<AccountDto> accountDtoList = JdbcTemplateUtils.builder(ModelConst.T_ACCOUNT).selectField("*")
                .in("id", accountIds)
                .queryForPOJOList(AccountDto.class);
        Assert.notEmpty(accountDtoList, "结算组织账户为空");

        Map<String, AccountDto> updateAccountMap = new HashMap<>();
        trades.stream().collect(Collectors.groupingBy(Trade::getDirection))
                .forEach(((tradeDirectionKey, tradeModes) -> {
                    if (tradeDirectionKey.equals(TradeDirection.Sale.name())) {
                        tradeModes.stream().collect(Collectors.groupingBy(Trade::getOrganization_id))
                                .forEach((organizationIdKey, tradeModesSub) -> {
                                    //获取组织
                                    OrganizationDto organization = tradeOrgList.stream().filter(t -> t.getId().equals(organizationIdKey.getId())).collect(Collectors.toList()).get(0);
                                    AccountDto cAccount = accountDtoList.stream().filter(t -> t.getId().equals(organization.getAccount_id())).findFirst().orElse(null);
                                    Assert.notNull(cAccount, "请联系平台客服为["+organization.getId()+"]添加结算账户");
                                    //获取客户账户
                                    if (updateAccountMap.containsKey(cAccount.getId())) {
                                        cAccount = updateAccountMap.get(cAccount.getId());
                                    } else {
                                        updateAccountMap.put(cAccount.getId(), cAccount);
                                    }
                                    BigDecimal availableLimit = cAccount.getAvailable_limit();

                                    //客户可用额度减少
                                    for (Trade trade : tradeModesSub) {
                                        availableLimit = BigDecimalUtils.sub(availableLimit, trade.getAmount());
                                    }
                                    cAccount.setAccount_balance(availableLimit);
                                    updateAccountMap.put(cAccount.getId(),cAccount);
                                });
                    } else {
                        tradeModes.stream().collect(Collectors.groupingBy(Trade::getOrganization_id))
                                .forEach((organizationIdKey, tradeModesSub) -> {
                                    //获取组织
                                    OrganizationDto organization = tradeOrgList.stream().filter(t -> t.getId().equals(organizationIdKey.getId())).collect(Collectors.toList()).get(0);
                                    //获取供应商账户
                                    AccountDto vAccount = accountDtoList.stream().filter(t -> t.getId().equals(organization.getAccount_id())).findFirst().orElse(null);
                                    Assert.notNull(vAccount, "请联系平台客服为["+organization.getId()+"]添加结算账户");

                                    if (updateAccountMap.containsKey(vAccount.getId())) {
                                        vAccount = updateAccountMap.get(vAccount.getId());
                                    } else {
                                        updateAccountMap.put(vAccount.getId(), vAccount);
                                    }
                                    BigDecimal accountBalance = vAccount.getAccount_balance();
                                    //供应商余额增加
                                    for (Trade trade : tradeModesSub) {
                                        accountBalance = BigDecimalUtils.add(accountBalance, trade.getAmount());
                                    }
                                    vAccount.setAccount_balance(accountBalance);
                                    updateAccountMap.put(vAccount.getId(), vAccount);

                                });
                    }
                }));

        updateAccountMap.forEach((key,value) -> accountService.update(value));

        AccountDto platformAccount = accountService.loadById(PlatformConst.ORGANIZATION_ACCOUND_ID);
        BigDecimal platformAvailableLimit = platformAccount.getAvailable_limit(), platformAccountBalance = platformAccount.getAccount_balance();

        for (Trade trade : trades) {
            if (trade.getDirection().equals(TradeDirection.Sale.name())) {
                //平台可用额度增加
                platformAvailableLimit = BigDecimalUtils.add(platformAvailableLimit, trade.getAmount());
            } else {
                //平台可用额度减少
                platformAccountBalance = BigDecimalUtils.sub(platformAccountBalance, trade.getAmount());
            }
        }
        platformAccount.setAccount_balance(platformAccountBalance);
        platformAccount.setAvailable_limit(platformAvailableLimit);
        accountService.update(platformAccount);



        stopWatch.stop();
        String prettyPrint = stopWatch.prettyPrint();
        log.info(prettyPrint);
        return true;
    }


}
